
// ui.

#define UNICODE
#define _UNICODE
#include "dph.h"
#include <exp.hpp>
#define FD L".\\resourcepack\\"
#define KEYPRESS(VK) (GetAsyncKeyState(VK)& 0x8000)
int typedef tick_t;
exim::Color transcolor = {0xff, 0x3c, 0xff};
exim::Color TransColor = {0xff, 0x3c, 0xff};
const COLORREF TRANSCOLOR = RGB(transcolor.r, transcolor.g, transcolor.b); //16711850ul
LPCWSTR dphlptx = L"按键: \n方向键: 移动。按shift可加速。\n上、下键+ctrl:调整窗口透明度。\nESC: \
关闭。\nH: 打开此窗口。\nM: 查看信息。\n左下角数字为CPU占用率, 右下角饼状图显示内存占用情况。";
enum __kb_pindex {
    KB_PW, KB_PA, KB_PS, KB_PD, KB_PVKSPACE, KB_PVKSHIFT, KB_PVKCTRL, KB_PVKLEFT, 
    KB_PVKRIGHT, KB_PVKUP, KB_PVKDOWN, KB_PVKLBUTTON, KB_PVKRBUTTON,
    KB_P_
};
enum __cat_decoration {
    CD_NONE, CD_SUNGLASSES, CD_BOWKNOT, CD_ALL
};
time_t StartTime = time(NULL);
time_t LastGetTrulyRunTime = StartTime;
LONG_PTR trtl = NULL;
WCHAR trtl_res[100];
inline void SetTrulyRunTime()
{
    time_t tn = time(NULL);
    auto dftime = (difftime(tn, LastGetTrulyRunTime));
    if (dftime < 82)
    {
        trtl += (LONG64)dftime;
        LastGetTrulyRunTime = tn;
    }
    else
    {
        LastGetTrulyRunTime = tn;
    }
    //trtl_msadd += await_t;
    //if (trtl_msadd >= 1000) {
    //    trtl ++ ;
    //    trtl_msadd -= 1000;
    // }
}
inline TCHAR* GetTrulyRunTimeLong()
{
    long long More = static_cast<long long>(trtl);
    int d, h, m, s;
    d = static_cast<int>( More / (24 * 60 * 60));
    More -= d * 24 * 3600;
    h = (int)(More / (3600));
    More -= h * 3600;
    m = (int)(More / 60);
    More -= m * 60;
    s = (int)(More);
    swprintf_s(trtl_res, 48, L"%d+%d:%d:%d", d, h, m, s);
    return trtl_res;
}
inline TCHAR* GetRunTimeLong()
{
    long long More = static_cast<long long>(difftime(time(NULL), StartTime));
    int d, h, m, s;
    d = static_cast<int>( More / (24 * 60 * 60));
    More -= d * 24 * 3600;
    h = (int)(More / (3600));
    More -= h * 3600;
    m = (int)(More / 60);
    More -= m * 60;
    s = (int)(More);
    swprintf_s(&trtl_res[50], 48, L"%d+%d:%d:%d", d, h, m, s);
    return &trtl_res[50];
}
int Width = 612/3;
int Height= 354/3;
int MEMR = (354-270) / 2 / 3; // 270 354; 520 612; 
int MEMY = (354+270) / 2 / 3;
int MEMX = (520+612) / 2 / 3;
int EYE1X = 240 / 3;
int EYE1Y = 130 / 3;
int EYE2X = 360 / 3;
int EYE2Y = 168 / 3;
int eye_radiu = 9 / 3;
WCHAR Title[60] = {'D', 'e', 's', 'k', 'P', 'e', 't'};
int winPosX = 0;
int winPosY = 0;
void TransferWindow(HWND winMain, int xadd, int yadd)
{
    RECT rect;
    GetWindowRect(winMain, &rect);
    int &x1 = winPosX, &y1 = winPosY;
    x1 = rect.left + xadd;
    y1 = rect.top + yadd;
    if (x1 > 1690 )
    {
        x1 = 1690;
    }else if(x1 < 0){
        x1 = 0;
    }
    if (y1 > 985){
        y1 = 985;
    } else if (y1 < 0) {
        y1 = 0;
    }
    MoveWindow(winMain, x1, y1, Width, Height, true);
}
void apie(int x, int y, int R,
    double percent // 0 ~ 100.0
)
{
    constexpr double PI = 3.14159265359;
    if (percent < 0.1) {
        return; // draw nil
    } else
    if (percent < 0.5) {
        percent = 0.5;
    } else if (percent > 99.2) {
        percent = 99.2;
    }
    double end_agl = 0.0;
    const double per = percent;
    int red = 0, green = 255, blue = 255; // auto color
    end_agl = per * 2 * PI / 100;
    if (per <= 33.333333){
        red = 0;
        green = 255;
        blue = (255 - exim::mid( static_cast<int>(per * 3 * 255 / 100) , 0, 255) );
    }
    else if (per <= 66.666667){
        red = exim::mid<int>((per - 33.333333) * 3 * 255 / 100, 0, 255);
        green = 255;
        blue = 0;
    }
    else {
        red = 255;
        green = 255 - exim::mid(static_cast<int>((per - 66.666667) * 3 * 255 / 100), 0, 255);
        blue = 0;
    }
    setfillcolor(RGB(red, green, blue));
    fillpie(x-R, y-R, x + R, y + R, 0, end_agl);
}
#define Dp_Speak(what) {speaking=true;speak=speak_time;swprintf_s(spktx, 56, L"%s",what);}
#define Dp_SpeakPrep() {speaking=true;speak=speak_time;}
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int iCmdShow) {
    exim::init(Width, Height, 0, L"simhei", 12);
    const HWND wMain = exim::DisplayInfo.win;
    exim::image __cat;
    __cat.load(FD L"cat.png", 0, 0);
    exim::image __keyboard;
    __keyboard.load(FD L"kb.png", 0, 0);
    exim::image __cat_sunglasses;
    __cat_sunglasses.load(FD L"sg.png", 0, 0);
    __cat.set_colorkey(TransColor);
    __keyboard.set_colorkey(TransColor);
    __cat_sunglasses.set_colorkey(TransColor);
    exim::image _kb_pany[KB_P_];
    exim::image kb_pany[KB_P_];
    const wchar_t *__kb_pstrs[KB_P_] = {
        FD L"kb_pw.png", FD L"kb_pa.png", FD L"kb_ps.png", FD L"kb_pd.png",
        FD L"kb_pvks.png", FD L"kb_pvksf.png", FD L"kb_pvkct.png",
        FD L"kb_pvkl.png", FD L"kb_pvkr.png", FD L"kb_pvku.png", FD L"kb_pvkd.png", 
        FD L"kb_pvklbt.png", FD L"kb_pvkrbt.png"
    };
    for(int i=0; i<KB_P_; i++) {
        _kb_pany[i].load(
            __kb_pstrs[i], 0, 0
        );
        _kb_pany[i].set_colorkey(TransColor);
        _kb_pany[i].scale(kb_pany[i], Width, Height);
    }
    exim::image __dlgbox;
    exim::image __weak;
    exim::image __bowknot;
    __dlgbox.load(FD L"dialogbox.png", 0, 0);
    __dlgbox.set_colorkey(TransColor);
    __weak.load(FD L"weak.png", 0, 0);
    __weak.set_colorkey(TransColor);
    __bowknot.load(FD L"bowknot.png", 0, 0);
    __bowknot.set_colorkey(TransColor);
    exim::image cat;
    exim::image keyboard;
    exim::image cat_sunglasses;
    exim::image dlgbox;
    exim::image cat_weak;
    exim::image cat_bowknot;
    __cat.scale(cat, Width, Height);
    __keyboard.scale(keyboard, Width, Height);
    __cat_sunglasses.scale(cat_sunglasses, Width, Height);
    __dlgbox.scale(dlgbox, Width, Height);
    __weak.scale(cat_weak, Width, Height);
    __bowknot.scale(cat_bowknot, Width, Height);
    
    BYTE Ap = 255;
    SetWindowPos(wMain, HWND_TOPMOST, 1500, 520, Width, Height, SWP_NOMOVE | SWP_NOSIZE);
    SetWindowLong(wMain, GWL_STYLE, GetWindowLong(wMain, GWL_STYLE) & ~WS_CAPTION);
    SetWindowLong(wMain, GWL_EXSTYLE, GetWindowLong(wMain, GWL_EXSTYLE) & (~(WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME)) | WS_EX_LAYERED | WS_EX_TOOLWINDOW);
    SetLayeredWindowAttributes(wMain, TRANSCOLOR, 128, LWA_COLORKEY);
    TransferWindow(wMain, 1, 1);
    
    wchar_t systxt[106] = {0};
    settextcolor(RGB(0xff, 0xeb-0xEB, 0x3b+255-59));
    const int text_height = textheight(L"QWERTYUIOPASDFGHJKLZXCVBNM09厵");
    tick_t gct = 0;
    double gcv = 100 * getcpu();
    long   gmv = getmem();
    
    tick_t adorn = 0;
    int decoration = CD_NONE;
    
    tick_t speak = 0;
    bool speaking = false;
    const tick_t speak_time = 128;
    COLORREF spkcol = RGB(0xff, 0x57, 0x22);
    wchar_t spktx[56] = {0};
    
    RECT winRect;
    POINT point;
    int eyedx = 0;
    int eyedy = 0;
    bool isdragging = false;
    POINT lastpoint;
    GetCursorPos(&lastpoint);
    
    BeginBatchDraw();
    while (TRUE)
    {
        Sleep(60);
        SetTrulyRunTime();
        gct++;
        adorn--;
        if(gct > 16) {
            gct = 0;
            gcv = 100.0 * getcpu();
            gmv = getmem();
        }
        if(adorn < 0) {
            adorn = exgame::randint(400, 1680);
            decoration = exgame::randint(0, CD_ALL-1);
        }
        if(speaking) {
            speak--;
            if(speak < 0) {
                speaking = false;
                speak = 0;
            }
        } else {
            speak++;
            if(speak > 960) {
                if(gmv > 65 && exgame::prob()) {
                    Dp_Speak(L"内存占用过高,请及时清理");
                }
                else if(gcv > 18 && exgame::prob()) {
                    Dp_Speak(L"房间里是不是有点热?");
                }
                else if(exgame::prob(20)){
                    Dp_Speak(L"按H获取帮助哦 ~");
                } else {
                    speak = 0;
                }
            } else if (exgame::prob((speak / 960 / 2) * 100)) {
                if(gmv > 65 && exgame::prob()) {
                    Dp_Speak(L"内存占用过高,请及时清理");
                }
                else if(gcv > 15 && exgame::prob()) {
                    Dp_Speak(L"房间里是不是有点热?");
                }
                else if (exgame::prob(20)) {
                    Dp_Speak(L"按H获取帮助哦 ~");
                }
                else {
                    speak = 0;
                }
            }
        }
        exim::draw.fill(transcolor);
        exim::draw.blit(cat, 0, 0);
        GetCursorPos(&point);
        if(GetForegroundWindow() == wMain){
            eyedx = (double)exim::mid<int>(winPosX + Width/2 - point.x, -480, 480) * 4 / 480.0;
            eyedy = (double)exim::mid<int>(winPosY + Height/2 - point.y, -480, 480) * 4 / 480.0;
            setfillcolor(BLACK);
            solidcircle(EYE1X - eyedx, EYE1Y - eyedy, eye_radiu);
            solidcircle(EYE2X - eyedx, EYE2Y - eyedy, eye_radiu);
        } else {
            setfillcolor(BLACK);
            solidcircle(EYE1X, EYE1Y, eye_radiu);
            solidcircle(EYE2X, EYE2Y, eye_radiu);
        }
        if(gmv > 80) {
            exim::draw.blit(cat_weak, 0, 0);
        }
        switch (decoration)
        {
        case CD_NONE: {
            pass;
        } break;
        
        case CD_SUNGLASSES: {
            exim::draw.blit(cat_sunglasses, 0, 0);
        } break;
        
        case CD_BOWKNOT: {
            exim::draw.blit(cat_bowknot, 0, 0);
        } break;
        
        default:
            break;
        }
        if(speaking) {
            exim::draw.blit(dlgbox, 0, 0);//400,20
            exim::draw.multitext(spktx, 343/3, 26/3, (562-343)/3, (172-36)/3, spkcol, 1, '\n');
        }
        exim::draw.blit(keyboard, 0, 0);
        if(KEYPRESS('W')) {
            exim::draw.blit(kb_pany[KB_PW], 0, 0);
        } if(KEYPRESS('A')) {
            exim::draw.blit(kb_pany[KB_PA], 0, 0);
        } if(KEYPRESS('S')) {
            exim::draw.blit(kb_pany[KB_PS], 0, 0);
        } if(KEYPRESS('D')) {
            exim::draw.blit(kb_pany[KB_PD], 0, 0);
        } if(KEYPRESS(VK_SPACE)) {
            exim::draw.blit(kb_pany[KB_PVKSPACE], 0, 0);
        } if(KEYPRESS(VK_SHIFT)) {
            exim::draw.blit(kb_pany[KB_PVKSHIFT], 0, 0);
        } if(KEYPRESS(VK_CONTROL)) {
            exim::draw.blit(kb_pany[KB_PVKCTRL], 0, 0);
        } if(KEYPRESS(VK_LEFT)) {
            exim::draw.blit(kb_pany[KB_PVKLEFT], 0, 0);
        } if(KEYPRESS(VK_RIGHT)) {
            exim::draw.blit(kb_pany[KB_PVKRIGHT], 0, 0);
        } if(KEYPRESS(VK_UP)) {
            exim::draw.blit(kb_pany[KB_PVKUP], 0, 0);
        } if(KEYPRESS(VK_DOWN)) {
            exim::draw.blit(kb_pany[KB_PVKDOWN], 0, 0);
        } if(KEYPRESS(VK_LBUTTON)) {
            exim::draw.blit(kb_pany[KB_PVKLBUTTON], 0, 0);
        } if(KEYPRESS(VK_RBUTTON)) {
            exim::draw.blit(kb_pany[KB_PVKRBUTTON], 0, 0);
        } 
        swprintf_s(systxt, 32, L"%.1lf%%", gcv);
        outtextxy(0, Height-text_height, systxt);
        apie(MEMX, MEMY, MEMR, (double)gmv);
        FlushBatchDraw();
        if(GetForegroundWindow() == wMain) {
            if(KEYPRESS(VK_ESCAPE)) {
                MessageBoxW(wMain, L"程序已退出(esc).", L"DeskPet", MB_OK);
                break;
            }
            if(KEYPRESS(VK_UP)) {
                if(KEYPRESS(VK_SHIFT)) {
                    TransferWindow(wMain, 0, -36);
                } else if(KEYPRESS(VK_CONTROL)) {
                    if(Ap <= 253) {
                        Ap += 2;
                        SetLayeredWindowAttributes(wMain, TRANSCOLOR, Ap, LWA_COLORKEY | LWA_ALPHA);
                        Dp_SpeakPrep();
                        swprintf_s(spktx, 56, L"透明度调整为%d", (int)Ap);
                    }
                } else {
                    TransferWindow(wMain, 0, -4);
                }
            } else if(KEYPRESS(VK_DOWN)) {
                if(KEYPRESS(VK_SHIFT)) {
                    TransferWindow(wMain, 0, 36);
                } else if(KEYPRESS(VK_CONTROL)) {
                    if(Ap >= 12) {
                        Ap -= 2;
                        SetLayeredWindowAttributes(wMain, TRANSCOLOR, Ap, LWA_COLORKEY | LWA_ALPHA);
                        Dp_SpeakPrep();
                        swprintf_s(spktx, 56, L"透明度调整为%d", (int)Ap);
                    }
                } else {
                    TransferWindow(wMain, 0, 4);
                }
            } else if(KEYPRESS(VK_LEFT)) {
                if(KEYPRESS(VK_SHIFT)) {
                    TransferWindow(wMain, -36, 0);
                } else {
                    TransferWindow(wMain, -4, 0);
                }
            } else if(KEYPRESS(VK_RIGHT)) {
                if(KEYPRESS(VK_SHIFT)) {
                    TransferWindow(wMain, 36, 0);
                } else {
                    TransferWindow(wMain, 4, 0);
                }
            }
            if (KEYPRESS('H')) {
                MessageBoxW(wMain, dphlptx, L"DeskPet", MB_OK);
            }
            else if (KEYPRESS('M')) {
                swprintf_s(systxt, 106, L"Sysinfo:\nCPU:%.1lf%%, Memory:%d%%\n运行时间:%s\n实际运行时间:%s",
                    gcv, gmv, GetRunTimeLong(), GetTrulyRunTimeLong());
                MessageBoxW(wMain, systxt, L"DeskPet", MB_OK);
            }
            if(KEYPRESS(VK_LBUTTON)) {
                if(isdragging){
                    int dx = point.x - lastpoint.x;
                    int dy = point.y - lastpoint.y;
                    TransferWindow(wMain, dx, dy);
                    lastpoint.x = point.x;
                    lastpoint.y = point.y;
                } else {
                    isdragging = true;
                    lastpoint.x = point.x;
                    lastpoint.y = point.y;
                }
            } else {
                isdragging = false;
            }
        } else {
            isdragging = false;
        }
        if(getStatr() == DPST_CLOSE) {
            MessageBoxW(wMain, L"程序已退出(close).", L"DeskPet", MB_OK);
            break;
        }
    }
    EndBatchDraw();
    closegraph();
    return 0;
}